#大模型请求url进行响应
import requests
from fastapi import APIRouter, HTTPException, Depends, Body
from pydantic import BaseModel, ValidationError, Field, root_validator
from typing import Optional, List, Dict, Any, Union
import json
import logging
import re
from .config import get_model_request_configs

# 设置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 对应 - 不使用字符串存储JSON，而是直接使用Python字典
requrest_body_dict = {
    "bill_check": {
        "cn_type": "对账单",
        "description": "处理时间约18秒",
        "request_body": {
            "model": "OpenGVLab/InternVL3-14B",
            "messages": [
                {
                    "role": "system", 
                    "content": "You are InternVL3. You are a helpful assistant.Answer in simplifed chinese."
                },
                {
                    "role": "user",
                    "content": [
                        {
                            "type": "text",
                            "text": "提取图片中的信息为json。对于不存在的内容不填即可，不要瞎编。提取字段如下（仅提取存在的内容)：{\"bank_statement\": {\"bank_name\": \"\",\"account_number\": \"\",\"account_name\": \"\",\"date_range\": \"\",\"transactions\": [{\"counterparty_account\": \"\",\"counterparty_name\": \"\",\"counterparty_bank\": \"\",\"date\": \"\",\"credit_amount\": null,\"debit_amount\": null,\"balance\": null,\"operator\": \"\",\"note\": \"\",\"summary\": \"\"}],\"summary\": {\"total_credit_count\": null,\"total_credit_amount\": null,\"total_debit_count\": null,\"total_debit_amount\": null},\"page_info_summary\": \"\",\"reconciliation_info\": \"\"},\"stamp\": {\"text\": \"\",\"location\": \"\"}}"
                        },
                        {
                            "type": "image_url",
                            "image_url": {
                                "url": "http://192.168.110.121:9000/misce-llaneous/2025/05/12/a3dae14189af45f383786d3d705a5b7b.png"
                            }
                        }
                    ]
                }
            ],
            "temperature": 0.8,
            "top_p": 0.9,
            "stream": False
        }
    },
}  


# 创建路由器
router = APIRouter(tags=["LLM请求"])

# 请求模型的数据结构
class LLMRequestData(BaseModel):
    """
    self_agent_body_data_type:非空且存在时自定义agent的body如{"self_agent_body_data_type": "bill_check",}。如果为空，则使用传递过来的body；
    
    当self_agent_body_data_type非空时，可以不提供其他字段
    当self_agent_body_data_type为空时，必须提供model和messages字段
    """
    model: Optional[str] = None
    messages: Optional[List[Dict[str, Any]]] = None
    temperature: Optional[float] = 0.7
    top_p: Optional[float] = 0.9
    stream: Optional[bool] = False
    self_agent_body_data_type: Optional[str] = ""

    class Config:
        # 防止传入额外的字段
        extra = "ignore"
    
    @root_validator(pre=True)
    def validate_fields(cls, values):
        # 检查self_agent_body_data_type
        body_type = values.get('self_agent_body_data_type')
        
        # 如果使用预定义模板，检查模板是否存在
        if body_type:
            if body_type not in requrest_body_dict:
                raise ValueError(f"预定义模板 '{body_type}' 不存在")
            # 当使用预定义模板时，不需要验证其他字段
            return values
        
        # 如果不使用预定义模板，检查必需字段
        if not values.get('model'):
            raise ValueError("当不使用预定义模板时，'model'字段是必需的")
        if not values.get('messages'):
            raise ValueError("当不使用预定义模板时，'messages'字段是必需的")
        
        return values

def request_llm(data: LLMRequestData):
    """
    向大模型发送请求并获取响应
    
    Args:
        data: 包含请求参数的对象
    
    Returns:
        dict: 模型返回的JSON响应
    """
    try:
        # 确定是否使用预定义模板
        using_predefined = data.self_agent_body_data_type and data.self_agent_body_data_type in requrest_body_dict
        
        # 处理请求体数据
        if using_predefined:
            logger.info(f"使用预定义请求体: {data.self_agent_body_data_type}")
            # 直接获取预定义的请求体字典
            body_data = requrest_body_dict[data.self_agent_body_data_type]["request_body"].copy()
            logger.info("成功获取预定义请求体")
            
            # 使用预定义模板中的模型名称获取请求配置
            model_name = body_data.get("model")
            if not model_name:
                logger.error("预定义模板中未提供模型名称")
                return {"error": "预定义模板中未提供模型名称"}
        else:
            logger.info("使用传入的参数构建请求体")
            # 使用传入的参数构建请求体
            body_data = {
                "model": data.model,
                "messages": data.messages,
                "temperature": data.temperature,
                "top_p": data.top_p,
                "stream": data.stream
            }
            model_name = data.model
        
        # 获取模型请求配置
        request_url, headers = get_model_request_configs(model_name)
        
        # 如果获取配置失败
        if request_url is False:
            logger.error(f"无法获取模型配置: {headers}")
            return {"error": headers}  # headers在这种情况下包含错误信息
        
        # 确保请求体是有效的JSON
        try:
            # 尝试序列化和反序列化以验证JSON有效性
            json_str = json.dumps(body_data)
            body_data = json.loads(json_str)
            logger.info("请求体JSON验证通过")
        except json.JSONDecodeError as e:
            logger.error(f"请求体JSON无效: {str(e)}")
            return {"error": f"请求体JSON无效: {str(e)}"}
        
        # 发送请求
        logger.info(f"发送请求到: {request_url}")
        try:
            response = requests.post(request_url, headers=headers, json=body_data)
        except requests.RequestException as e:
            logger.error(f"请求发送失败: {str(e)}")
            return {"error": f"请求发送失败: {str(e)}"}
        
        # 检查响应状态
        if response.status_code != 200:
            error_msg = f"请求失败，状态码: {response.status_code}, 详情: {response.text}"
            logger.error(error_msg)
            return {
                "error": error_msg,
                "details": response.text
            }
        
        # 返回响应
        logger.info("请求成功")
        return response.json()
    except json.JSONDecodeError as e:
        error_msg = f"JSON解析错误: {str(e)}"
        logger.error(error_msg)
        return {"error": error_msg}
    except Exception as e:
        error_msg = f"请求过程中发生错误: {str(e)}"
        logger.error(error_msg)
        return {"error": error_msg}

# API端点
@router.post("/llm_request")
async def llm_request(data: LLMRequestData = Body(...)):
    """
    大模型请求API接口
    """
    try:
        logger.info(f"接收到请求: 模型={data.model}, self_agent_body_data_type={data.self_agent_body_data_type}")
        logger.debug(f"请求详情: {data.dict()}")
        
        response = request_llm(data)
        if "error" in response:
            error_msg = response["error"]
            logger.error(f"请求处理出错: {error_msg}")
            raise HTTPException(status_code=500, detail=error_msg)
        return response
    except ValidationError as e:
        logger.error(f"请求数据验证错误: {str(e)}")
        raise HTTPException(status_code=400, detail=f"请求数据验证错误: {str(e)}")
    except Exception as e:
        logger.error(f"处理请求时发生未知错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"处理请求时发生未知错误: {str(e)}")


# 示例调用代码（仅供测试，实际部署时可以注释掉）
if __name__ == "__main__":
    # 示例1: 完整参数请求
    test_data = LLMRequestData(
        model="InternVL3-14B",
        messages=[
            {
                "role": "system",
                "content": "You are InternVL3. You are a helpful assistant.Answer in simplifed chinese."
            },
            {
                "role": "user",
                "content": [
                    {
                        "type": "text",
                        "text": "Describe the image please"
                    },
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": "https://static.openxlab.org.cn/internvl/demo/visionpro.png"
                        }
                    }
                ]
            }
        ],
        temperature=0.8,
        top_p=0.9,
        stream=False
    )
    
    print("\n=== 测试完整参数请求 ===")
    result = request_llm(test_data)
    print(json.dumps(result, indent=2, ensure_ascii=False))
    
    # 示例2: 使用预定义模板请求
    template_test = LLMRequestData(
        self_agent_body_data_type="bill_check"
    )
    
    print("\n=== 测试预定义模板请求 ===")
    result = request_llm(template_test)
    print(json.dumps(result, indent=2, ensure_ascii=False))